package me

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/widget"
	"github.com/bitfield/script"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/saintfish/chardet"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

// 按行数分页查看文本文件内容
func ViewText(txtpath string, u fyne.ListableURI) {
	lblPage := canvas.NewText("", Red)

	// lns, _ := script.File(txtpath).CountLines()
	// CvsCharSet.Text = fmt.Sprintf("共 %6d 行", lns)
	lns := 0
	rs := []string{}
	script.File(txtpath).FilterScan(func(line string, w io.Writer) {
		lns++
		rs = append(rs, line)
	}).Wait()

	// rs, _ := script.File(txtpath).Slice()
	bp := NewPage(lns, 200)

	detector := chardet.NewTextDetector()
	setContent := func(l, r int) {
		if bp != nil {
			t1 := time.Now()
			ss := strings.Join(rs[l:r], "\n")
			charset, _ := detector.DetectBest([]byte(ss))
			if charset.Language == "zh" {
				ss, _, _ = transform.String(simplifiedchinese.GBK.NewDecoder(), ss)
			}
			CvsCharSet.Text = fmt.Sprintf("共 %6d 行 : ", lns) +
				charset.Language + ":" + charset.Charset
			CvsCharSet.Refresh()
			TxtEntry.SetText(ss)
			lblPage.Text = fmt.Sprintf("P%3d/%3d", bp.CurPage(), bp.TotalPage())
			lblPage.Refresh()
			CvsMsg.Text = gconv.String(time.Since(t1).Milliseconds()) + " ms Used."
			CvsMsg.Refresh()
		}
	}

	fbtns := FourBtns(func() {
		setContent(bp.First())
	}, func() {
		setContent(bp.Prev())
	}, func() {
		setContent(bp.Next())
	}, func() {
		setContent(bp.Last())
	})
	btnAll := widget.NewButton("All", func() {
		AsyncCall1(5, func() {
			setContent(0, len(rs))
		}, func() {
			TxtEntry.SetText("读取文件超时,请使用系统默认应用程序打开")
		})
	})
	pageToGo := 1
	btnGo := widget.NewButton("Go", func() {
		bp.GetPage(pageToGo)
		setContent(bp.CurIndexs())
	})
	eni := widget.NewEntryWithData(binding.IntToString(binding.BindInt(&pageToGo)))
	eni.OnSubmitted = func(s string) {
		btnGo.OnTapped()
	}
	btnSave := widget.NewButton("Save", func() {
		dl := dialog.NewFileSave(func(uc fyne.URIWriteCloser, err error) {
			if err != nil {
				dialog.ShowError(err, Win)
				return
			}
			if uc == nil {
				// log.Println("Cancelled")
				return
			}
			gfile.PutContents(uc.URI().Path(), TxtEntry.Text)
		}, Win)
		dl.SetLocation(u)
		dl.Show()
	})
	btnClear := widget.NewButton("Clear", func() {
		TxtEntry.SetText("")
	})
	SetObjs(Right, container.NewBorder(container.NewPadded(
		container.NewHBox(fbtns, btnAll, lblPage, eni, btnGo, btnClear, btnSave)),
		container.NewHBox(CvsCharSet, widget.NewSeparator(), CvsMsg),
		nil, nil, TxtEntry))
	setContent(bp.First())
}

// 按字节数 []rune 分页查看文本文件内容
func ViewText2(txtpath string) {
	lblPage := canvas.NewText("", Red)
	bs, err := os.ReadFile(txtpath)
	if err != nil {
		lblPage.Text = err.Error()
		lblPage.Refresh()
		return
	}
	detector := chardet.NewTextDetector()
	charset, err := detector.DetectBest(bs)
	if err != nil {
		lblPage.Text = err.Error()
		lblPage.Refresh()
	}

	// println(charset.Charset)
	// println(charset.Language)
	CvsCharSet.Text = charset.Language + ":" + charset.Charset
	CvsCharSet.Refresh()
	if charset.Language == "zh" {
		bs = GbkToUtf8(bs)
	}
	rs := bytes.Runes(bs)
	bp := NewPage(len(rs), 4000)

	setContent := func(l, r int) {
		if bp != nil {
			TxtEntry.SetText(string(rs[l:r]))
			lblPage.Text = fmt.Sprintf("P%d/%d", bp.CurPage(), bp.TotalPage())
			lblPage.Refresh()
		}
	}

	// setContent(bp.First())
	fbtns := FourBtns(func() {
		setContent(bp.First())
	}, func() {
		setContent(bp.Prev())
	}, func() {
		setContent(bp.Next())
	}, func() {
		setContent(bp.Last())
	})
	btnAll := widget.NewButton("All", func() {
		AsyncCall1(5, func() {
			setContent(0, len(rs))
		}, func() {
			TxtEntry.SetText("读取文件超时,请使用系统默认应用程序打开")
		})
	})
	pageToGo := 1
	btnGo := widget.NewButton("Go", func() {
		bp.GetPage(pageToGo)
		setContent(bp.CurIndexs())
	})
	eni := widget.NewEntryWithData(binding.IntToString(binding.BindInt(&pageToGo)))
	eni.OnSubmitted = func(s string) {
		btnGo.OnTapped()
	}

	SetObjs(Right, container.NewBorder(container.NewPadded(
		container.NewHBox(fbtns, btnAll, lblPage, eni, btnGo)),
		CvsCharSet, nil, nil, TxtEntry))
	setContent(bp.First())
}

// 按字节数 []rune 分页查看文本文件内容
func ViewText3(txtpath string) {
	lblPage := canvas.NewText("", Red)
	bs, err := os.ReadFile(txtpath)
	if err != nil {
		lblPage.Text = err.Error()
		lblPage.Refresh()
		return
	}
	detector := chardet.NewTextDetector()
	charset, err := detector.DetectBest(bs)
	if err != nil {
		lblPage.Text = err.Error()
		lblPage.Refresh()
	}

	CvsCharSet.Text = charset.Language + ":" + charset.Charset
	CvsCharSet.Refresh()
	if charset.Language == "zh" {
		bs = GbkToUtf8(bs)
	}
	rs := bytes.Runes(bs)
	// println(len(rs))
	// println(RuneSliceWidth(rs))
	bp := NewPage(RuneSliceWidth(rs), 4000)

	setContent := func(l, r int) {
		if bp != nil {
			TxtEntry.SetText(string(RuneSliceWidthRange(rs,l,r)))
			lblPage.Text = fmt.Sprintf("P%d/%d", bp.CurPage(), bp.TotalPage())
			lblPage.Refresh()
		}
	}

	// setContent(bp.First())
	fbtns := FourBtns(func() {
		setContent(bp.First())
	}, func() {
		setContent(bp.Prev())
	}, func() {
		setContent(bp.Next())
	}, func() {
		setContent(bp.Last())
	})
	btnAll := widget.NewButton("All", func() {
		AsyncCall1(5, func() {
			setContent(0, len(rs))
		}, func() {
			TxtEntry.SetText("读取文件超时,请使用系统默认应用程序打开")
		})
	})
	pageToGo := 1
	btnGo := widget.NewButton("Go", func() {
		bp.GetPage(pageToGo)
		setContent(bp.CurIndexs())
	})
	eni := widget.NewEntryWithData(binding.IntToString(binding.BindInt(&pageToGo)))
	eni.OnSubmitted = func(s string) {
		btnGo.OnTapped()
	}

	SetObjs(Right, container.NewBorder(container.NewPadded(
		container.NewHBox(fbtns, btnAll, lblPage, eni, btnGo)),
		CvsCharSet, nil, nil, TxtEntry))
	setContent(bp.First())
}

func ViewText1(txtpath string) {
	// t1 := time.Now()
	AsyncCall1(5, func() {
		bs, err := os.ReadFile(txtpath)
		// print("read file in(ms)")
		// t2 := time.Now()
		// println(time.Since(t1).Milliseconds())
		if err != nil {
			TxtEntry.SetText(err.Error())
			return
		}
		TxtEntry.SetText(string(bs))
	}, func() {
		TxtEntry.SetText("读取文件超时,请使用系统默认应用程序打开")
	})

	// println(time.Since(t2).Milliseconds())
}
